/*2S7LXljdWdGhrCxZ1MFl4nbo76lbmNV/zj9vAsZ4TsJjt35I/W4VBwuu/33I9fcb*/
/*
 * @Author: hufei 
 * @PageInfo: 半结构化文档管理弹窗-- 需求:单文件上传, 格式doc/docx, 上传最大限制 50MB
 * @Date: 2019-02-19 09:08:45 
 * @Last Modified by: tianzhyw
 * @Last Modified time: 2022-04-22 10:40:50
 */
import React, { Component } from 'react';
import { cipherTextTools, base, ajax, promptBox, formDownload } from 'nc-lightapp-front';
import { bytesToSize, decryptResponse } from './methods';
import img from './img.png';
import request from './request';
import './index.less';
import DataSourceDlg from 'scmpub/scmpub/components/DataSourceDlg';
import SCMUpload from './SCMUpload';
import { initLang, getLangByResId } from '../../../../../scmpub/scmpub/pub/tool/multiLangUtil';

let {
	NCModal: Modal,
	NCButton: Button,
	NCCheckbox: Checkbox,
	NCTooltip: Tooltip,
	NCProgressBar: ProgressBar,
	NCPopconfirm: PopConfirm
} = base;
let { Header, Body, Title } = Modal;
// TODO:
// 1. 数据源配置弹窗, 半结构化输出接口
// 2. 批量删除接口需要满足数组删除
// 3. 参数需要billId,fullPath,pk_doc(只下载用)
// 4. 多语抽取

let Service = {
	// 查询已上传附件列表
	queryAttachments: '/nccloud/ct/oba/query.do',
	// 上传附件接口
	uploadAttachment: '/nccloud/ct/oba/upload.do',
	// 附件下载接口
	downloadAttachment: '/nccloud/ct/oba/download.do',
	// 附件删除接口
	delAttachment: '/nccloud/ct/oba/delete.do',
	// 半结构化输出接口
	outputAttachment: '/nccloud/ct/oba/output.do'
};

export default class DocManagement extends Component {
	constructor(props) {
		super(props);
		this.state = {
			show: false, // 显示上传弹窗
			tip: '', // 显示上传校验不通过提示
			allCheck: false,
			dataList: [], // 包含从后台请求回来的数据和新上传的数据
			showTree: false // 结构化附件数据源配置弹框
		};
		this.requestList = new Map(); // 上传请求列表,用于取消上传
		this.billId = null; // 单据ID
		this.billType = null; // 单据类型
		initLang(this, [ '4004pub' ], 'ct');
	}

	componentWillReceiveProps(nextProps) {
		if (nextProps.show !== this.props.show && nextProps.show) {
			if (nextProps.show) {
				this.setState({
					dataList: [],
					tip: '',
					allCheck: false
				});
				this.billId = nextProps.billId;
				this.billType = nextProps.billType;
				this.getAttachData();
			}
		}
	}

	// 请求后台已有的的附件信息
	getAttachData = () => {
		ajax({
			url: Service.queryAttachments,
			data: { billId: this.billId, billType: this.billType },
			success: (res) => {
				res.data.forEach((item) => (item.renderType = 2)); // 给请求回来的数据增加renderType:2
				this.setState({
					dataList: res.data
				});
			}
		});
	};

	// 全选复选框的勾选事件
	allCheckChange = (value) => {
		this.state.dataList.forEach((item) => (item.checked = value));
		this.setState({
			allCheck: value
		});
	};

	// 列表条目复选框的勾选事件
	itemCheckChange = (index, value) => {
		this.state.dataList[index].checked = value;
		let allCheck = this.state.dataList.filter((item) => item.show !== false).every((item) => item.checked == true);
		this.setState({
			allCheck,
			dataList: this.state.dataList
		});
	};

	/*
	* 处理上传状态
	* -1 上传失败    （上传出错， 或者上传有响应且上传结束但响应结果为false）
	* 0  上传过程中  （上传在进行中）
	* 1  上传成功    （上传有响应，且上传结束，且响应结果为true）
	* 2  其他        （上传没响应，）
	*/
	handleUploadStatus(item) {
		// status为以下参数： uploading, done, error, removed
		let { status, error, success, isUpload } = item;
		let renderType;
		if (status === 'done' && success && !!isUpload) {
			renderType = 1;
		} else if (status === 'error' || (status === 'done' && !success)) {
			renderType = -1;
		} else if (status === 'uploading') {
			renderType = 0;
		} else if (!status || (status === 'done' && success && !isUpload)) {
			// 没有状态为查询，或者上次上传 本次不上传
			renderType = 2;
		} else if (status === 'removed') {
			renderType = 3;
		}
		return renderType;
	}

	// 渲染上传状态信息
	renderStatusDom = (item) => {
		let statusDom;
		switch (item.renderType) {
			case -1:
				// 上传失败
				statusDom = (
					<Tooltip
						container={document.querySelector('.upload-list')}
						inverse
						overlay={item.error || ''}
						placement="top"
						className="status-error-tip"
					>
						<span className="status-error animated">
							<i class="iconfont icon-zhuyi1" />
							{getLangByResId(this, '4004PUB-000012')}
							{/* 国际化处理： 上传失败*/}
						</span>
					</Tooltip>
				);
				break;
			case 0:
				// 上传中
				statusDom = [
					<span className="upload-percent">{`${item.percent ? parseInt(item.percent, 10) : 0}%`}</span>,
					<ProgressBar
						size="sm"
						active
						colors="success"
						now={item.percent ? parseInt(item.percent, 10) : 0}
					/>
				];
				break;
			case 1:
				// 上传成功
				statusDom = (
					<span className="status-success animated fadeOut">
						<i class="iconfont icon-wancheng" />
						{getLangByResId(this, '4004PUB-000013')} {/* 国际化处理： 上传成功*/}
					</span>
				);
				break;
			case 2:
				statusDom = null;
				break;
			default:
				status = null;
		}
		return statusDom;
	};

	// 渲染列表操作信息
	renderOperationList = (item, index) => {
		let operationList;
		switch (item.renderType) {
			case -1:
				operationList = (
					<span className="options">
						<a
							onClick={() => {
								this.reUpload(item, index);
							}}
							fieldid="ReUpload_Btn"
						>
							{getLangByResId(this, '4004PUB-000014')}
							{/* 国际化处理： 重新上传*/}
						</a>
						{/* 这里的忽略只需要删除列表数据即可 */}
						<a onClick={() => this.removeListItem(item, index)} fieldid="Ignore_Btn">
							{getLangByResId(this, '4004PUB-000015')}
						</a>
						{/* 国际化处理： 忽略*/}
					</span>
				);
				break;
			case 0:
				operationList = (
					<span className="options">
						{/* 这里的删除需要中断上传,并删除界面列表数据 */}
						<PopConfirm
							trigger="click"
							placement="left"
							content={getLangByResId(this, '4004PUB-000008')} /* 国际化处理： 确定要删除吗？*/
							onClose={() => {
								this.abortRequest(item, index);
							}}
						>
							<a fieldid="LineDel_btn">
								{getLangByResId(this, '4004PUB-000005')}
								{/* 国际化处理： 删除*/}
							</a>
						</PopConfirm>
					</span>
				);
				break;
			case 1:
			case 2:
				operationList = (
					<span className="options">
						<a onClick={() => this.handleOutput(item)} fieldid="Output_btn">
							{getLangByResId(this, '4004PUB-000016')}
						</a>
						{/* 国际化处理：半结构化输出*/}
						<a onClick={() => this.handleDownload(item)} fieldid="DownLoad_btn">
							{getLangByResId(this, '4004PUB-000017')}
						</a>
						{/* 国际化处理：下载文件*/}
						{/* <a>阅览</a> */}
						{/* 这里的删除需要删除后台数据,然后删除界面列表数据 */}
						<PopConfirm
							trigger="click"
							placement="left"
							content={getLangByResId(this, '4004PUB-000008')} /* 国际化处理： 确定要删除吗？*/
							onClose={() => {
								this.delListItem(item, index);
							}}
						>
							<a fieldid="Del_btn">
								{getLangByResId(this, '4004PUB-000005')}
								{/* 国际化处理： 删除*/}
							</a>
						</PopConfirm>
					</span>
				);
				break;
			default:
				operationList = null;
				break;
		}
		return operationList;
	};

	// 上传前的校验
	beforeUploadTest = (file) => {
		// 文件大小校验
		let curSize = parseFloat(bytesToSize(file.size, 2, 2)); // MB
		let { limitSize = 50 } = this.props; // MB
		if (curSize > limitSize) {
			this.setState({
				tip: `${getLangByResId(this, '4004PUB-000018')} ${limitSize}MB ${getLangByResId(
					this,
					'4004PUB-000019'
				)}，${getLangByResId(this, '4004PUB-000020')}！` /* 国际化处理： 允许上传的文件大小限制在,以内,请重新选择文件*/
			});
			return false;
		}
		// 文件格式校验
		let reg = /\.docx?$/;
		if (!reg.test(file.name)) {
			this.setState({
				tip: getLangByResId(this, '4004PUB-000009') /* 国际化处理： 只允许上传 doc/docx 格式的文档，请重新选择文件上传*/
			});
			return false;
		}
		return true;
	};

	// 文件上传请求
	uploadRequest = (file, isReUpload) => {
		// 上传前先进行大小和格式校验
		if (!isReUpload) {
			if (!this.beforeUploadTest(file)) {
				return;
			}
		}
		const randomNum = this.randomNum();
		let options = {
			filename: 'file',
			file,
			action: Service.uploadAttachment,
			withCredentials: false,
			data: {
				billId: this.billId,
				billType: this.billType
			},
			headers: {
				crux: randomNum
			},
			onStart: (event) => {
				let e = {
					isTrusted: event.isTrusted,
					percent: event.percent
				};
				// 这里要判断是不是重新上传,不是重新上传时要在dataList里面新增一项本次上传的信息
				if (!isReUpload) {
					let newItem = {
						uid: file.uid,
						name: file.name,
						status: 'uploading',
						isUpload: true,
						checked: false,
						show: true,
						percent: 0,
						error: null,
						originFileObj: file
					};
					this.state.dataList.push(newItem);
				}
				this.buildInfo(file, e, undefined, isReUpload, null);
			},
			onProgress: (event) => {
				let e = {
					isTrusted: event.isTrusted,
					percent: event.percent
				};
				this.buildInfo(file, e, undefined, isReUpload, null);
			},
			onSuccess: (response) => {
				this.buildInfo(file, undefined, response, isReUpload, randomNum);
			},
			onError: () => {
				this.buildInfo(file, undefined, undefined, isReUpload, null);
			}
		};
		let req = request(options);
		this.requestList.set(file.uid, req);
	};

	/**
 	* 取得随机数
 	*/
	randomNum = () => {
		const crypto = window.crypto || window.msCrypto;
		var array = new Uint32Array(1);
		let rNum = crypto.getRandomValues(array)[0];
		return rNum;
	};

	// 组装info数据结构
	buildInfo = (file, event, response, isReUpload, randomNum) => {
		let info = {
			file: {
				lastModified: file.lastModified,
				lastModifiedDate: file.lastModifiedDate,
				name: file.name,
				originFileObj: file,
				percent: file.percent,
				size: file.size,
				status: file.status,
				type: file.type,
				uid: file.uid
			}
		};
		if (event) {
			info.event = event;
			info.file.percent = event.percent;
			info.file.status = 'uploading';
		}
		if (response) {
			info.file.status = 'done';
			info.file.percent = 100;
			// info.file.response = decryptResponse(response);
			info.file.response = cipherTextTools.unZipAndDecrypt(response, randomNum);
		}
		if (!event && !response) {
			info.file.status = 'error';
			info.file.response = {
				error: {
					tip: getLangByResId(this, '4004PUB-000010') /* 国际化处理： 网络请求出错*/
				},
				success: false
			};
		}
		this.onUploadChange(info, isReUpload);
	};

	// 上传过程中信息处理
	onUploadChange = (info, isReUpload) => {
		let { uid, status, response, percent } = info.file;
		let { dataList } = this.state;
		let curUpload = dataList.find((item) => item.uid === uid);
		curUpload.percent = percent;
		curUpload.status = status;
		curUpload.error = (response && response.error && response.error.message) || null;
		curUpload.success = (response && response.success) || false;
		curUpload.renderType = this.handleUploadStatus(curUpload);
		if (status === 'done' && response) {
			Array.isArray(response.data) && Object.assign(curUpload, response.data[0]); // 将上传成功后台返回的信息合并到 state 中对应的 item 上
		}
		this.setState({ dataList });
	};

	// 重新上传
	reUpload = (item, index) => {
		let reUploadItem = this.state.dataList[index];
		let file = reUploadItem.originFileObj;
		this.uploadRequest(file, true);
	};

	// 文件下载
	handleDownload = (item) => {
		const { isdoc = true, pk_doc, name } = item;
		formDownload({
			params: { isdoc, pk_doc, name },
			url: Service.downloadAttachment,
			enctype: 1
		});
	};

	// 半结构化输出
	handleOutput = (item) => {
		const { isdoc = true, pk_doc, name } = item;
		formDownload({
			params: { isdoc, pk_doc, name, billId: this.billId, billType: this.billType },
			url: Service.outputAttachment,
			enctype: 1
		});
	};

	// 顶部删除按钮事件批量删除
	delCheckedList = () => {
		let { dataList } = this.state;
		dataList.forEach((item, index) => {
			let { checked, show, isUpload, success, status } = item;
			if (show && checked) {
				if (!isUpload || (isUpload && success)) {
					// 查询回来的和上传成功的
					this.delListItem(item, index);
				} else if (isUpload && !success && status == 'uploading') {
					// 正在上传过程中的
					this.abortRequest(item, index);
				} else if (isUpload && !success && status == 'done') {
					// 上传失败的
					this.removeListItem(item, index);
				}
			}
		});
		this.setState({
			dataList,
			allCheck: false
		});
	};

	// 上传过程中点击删除要中断上传并从界面删除
	abortRequest = (item, index) => {
		this.requestList.get(item.uid).abort();
		this.removeListItem(item, index);
	};

	// 上传成功后点击删除向后台发送删除请求, 后台删除成功后从界面删除
	delListItem = (item, index) => {
		ajax({
			url: Service.delAttachment,
			data: {
				billId: item.billId,
				fullPath: item.fullPath,
				pk_doc: item.pk_doc
			},
			loading: true,
			loadingContainer: this.refs.uploadList,
			success: (res) => {
				if (res.success) {
					this.removeListItem(item, index);
				}
			}
		});
	};

	// 上传失败后点击界面的忽略, 从界面删除单个列表项
	removeListItem = (item, index) => {
		let { dataList } = this.state;
		dataList[index].show = false;
		dataList[index].checked = false;
		this.setState({ dataList });
	};

	// 点击上传按钮时, 隐藏掉附件大小超过限制的提示信息
	hideTip = () => {
		if (this.state.tip) {
			this.setState({ tip: '' });
		}
	};

	handleShowTree = () => {
		this.setState({
			showTree: !this.state.showTree
		});
	};
	render() {
		const config = {
			accept: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/msword', // doc和docx格式
			uploadRequest: this.uploadRequest //文件选择后,拿到文件信息,并开始上传
		};
		let { dataList, showTree } = this.state;
		let { billType, asyncTree } = this.props;
		let emptyFlag = dataList.filter((item) => item.show !== false).length == 0;

		return (
			<div>
				<Modal
					show={this.props.show}
					onHide={this.props.toggleShow}
					className="scm-upload"
					width="720px"
					height="510px"
				>
					<Header closeButton>
						<Title>{getLangByResId(this, '4004PUB-000021')}</Title>
						{/* 国际化处理： 半结构化文档管理*/}
					</Header>
					<Body>
						<div className="top-box">
							<Checkbox
								disabled={!dataList.some((item) => item.show !== false)}
								className="allCheck"
								checked={!!this.state.allCheck}
								onChange={this.allCheckChange}
							/>
							<div className="btns">
								<SCMUpload {...config}>
									<Button onClick={this.hideTip} fieldid="Upload">
										{getLangByResId(this, '4004PUB-000022')}
									</Button>
									{/* 国际化处理： 上传文件*/}
								</SCMUpload>
								<Button onClick={this.handleShowTree} fieldid="DataSourceConfig">
									{getLangByResId(this, '4004PUB-000023')}
								</Button>
								{/* 国际化处理： 数据源配置*/}
								<Button
									disabled={!dataList.some((item) => item.checked)}
									onClick={() =>
										promptBox({
											color: 'warning',
											title: getLangByResId(this, '4004PUB-000005') /* 国际化处理： 删除*/,
											content: getLangByResId(this, '4004PUB-000011') /* 国际化处理： 确定要删除所选数据吗？*/,
											beSureBtnClick: this.delCheckedList
										})}
									fieldid="Del"
								>
									{getLangByResId(this, '4004PUB-000005')}
									{/* 国际化处理： 删除*/}
								</Button>
							</div>
						</div>
						<ul className="upload-list" ref="uploadList">
							{dataList.map((item, index) => {
								if (item.checked != true) {
									item.checked = false;
								}
								if (item.status == 'removed') {
									item.show = false;
								}
								if (item.show !== false) {
									item.show = true;
									return (
										<li>
											<Checkbox
												className="itemCheck"
												checked={item.checked}
												onChange={(value) => this.itemCheckChange(index, value)}
												fieldid="Select"
											/>
											<span className="file-name" title={item.name}>
												{item.name}
											</span>
											<span className={'file-status'}>{this.renderStatusDom(item)}</span>
											{this.renderOperationList(item, index)}
										</li>
									);
								}
							})}
							<div className={emptyFlag ? 'empty-list' : 'hide'}>
								<img src={img} />
								<div className="info">{getLangByResId(this, '4004PUB-000024')}</div>
								{/* 国际化处理： 文件为空*/}
								<SCMUpload {...config}>
									<a className="upload" onClick={this.hideTip}>
										{getLangByResId(this, '4004PUB-000022')} {/* 国际化处理： 上传文件*/}
									</a>
								</SCMUpload>
							</div>
						</ul>
						{this.state.tip && (
							<div className="test-tip">
								<i className="iconfont icon-zhuyi1" />
								{this.state.tip}
								<i
									className="iconfont icon-guanbi"
									onClick={() => {
										this.setState({ tip: '' });
									}}
								/>
							</div>
						)}
					</Body>
				</Modal>
				{/* 数据源配置弹窗 */}
				<DataSourceDlg show={showTree} billType={billType} asyncTree={asyncTree} close={this.handleShowTree} />
			</div>
		);
	}
}
// ReactDOM.render(<DocManagement />, document.getElementById('app'));

/*2S7LXljdWdGhrCxZ1MFl4nbo76lbmNV/zj9vAsZ4TsJjt35I/W4VBwuu/33I9fcb*/